package com.shenmazong.demo1907amongo.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shenmazong.demo1907amongo.mapper.ITbBlogMapper;
import com.shenmazong.demo1907amongo.pojo.TbBlog;
import com.shenmazong.demo1907amongo.service.ITbBlogService;
import com.shenmazong.demo1907amongo.utils.ResultResponse;
import com.shenmazong.demo1907amongo.vo.KeyWordVo;
import com.shenmazong.demo1907amongo.vo.PageVo;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.client.indices.AnalyzeResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2021/12/14 15:43
 */

@Service
public class TbBlogService implements ITbBlogService {

    @Autowired
    ITbBlogMapper iTbBlogMapper;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public ResultResponse list(PageVo pageVo) {

        Page<TbBlog> page = new Page<TbBlog>(pageVo.getPageNum(), pageVo.getPageSize());
        IPage<TbBlog> blogs = iTbBlogMapper.selectPage(page, null);

        return ResultResponse.SUCCESS(blogs);
    }

    @Override
    public ResultResponse del(Integer blogId) {
        TbBlog tbBlog = iTbBlogMapper.selectById(blogId);
        if(tbBlog == null) {
            return ResultResponse.FAILED(404, "该博客不存在,删除失败");
        }

        //-- 删除数据库
        int delete = iTbBlogMapper.deleteById(blogId);

        //-- 删除es
        elasticsearchRestTemplate.delete(tbBlog);
//        elasticsearchRestTemplate.delete(String.valueOf(blogId), TbBlog.class);

        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse add(TbBlog tbBlog) {

        //--1 向数据库添加
        tbBlog.setEsFlag(1);
        iTbBlogMapper.insert(tbBlog);

        //--2 同步到es中
        TbBlog blog = iTbBlogMapper.selectById(tbBlog.getBlogId());
        elasticsearchRestTemplate.save(blog);

        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse getBlogById(Integer id) {
        TbBlog tbBlog = iTbBlogMapper.selectById(id);
        if(tbBlog == null) {
            return ResultResponse.FAILED(404, "该博客不存在");
        }

        return ResultResponse.SUCCESS(tbBlog);
    }

    @Override
    public ResultResponse updateBlogById(TbBlog tbBlog) {
        TbBlog blog = iTbBlogMapper.selectById(tbBlog.getBlogId());
        if(blog == null) {
            return ResultResponse.FAILED(404, "该博客不存在,无法修改");
        }

        // 修改数据库
        BeanUtils.copyProperties(tbBlog, blog);
        blog.setEsFlag(1);
        iTbBlogMapper.updateById(blog);

        // 修改es
        elasticsearchRestTemplate.save(blog);

        return ResultResponse.SUCCESS(blog);
    }

    @Override
    public ResultResponse getBlogByKeyword(KeyWordVo keyWord) {

        // 参数保护
        if(keyWord.getPageNum() == null || keyWord.getPageNum()<=0) {
            keyWord.setPageNum(0);
        }
        else {
            keyWord.setPageNum(keyWord.getPageNum()-1);
        }
        if(keyWord.getPageSize() == null || keyWord.getPageSize()<=0) {
            keyWord.setPageNum(2);
        }

        // 分页信息
        Pageable pageable = PageRequest.of(keyWord.getPageNum(), keyWord.getPageSize());

        // 构造查询条件
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //-- 精确搜索
        //NativeSearchQuery query = builder.withPageable(pageable).withQuery(QueryBuilders.termQuery("blogTitle", keyWord.getKeyWork())).build();

        //-- 分词搜索
        //NativeSearchQuery query = builder.withPageable(pageable).withQuery(QueryBuilders.matchQuery("blogTitle", keyWord.getKeyWork())).build();

        //-- 排序
        SortBuilder order = new FieldSortBuilder("blogId").order(SortOrder.ASC);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>").postTags("</font>").field("blogTitle");

        //-- 多字段查询(多个条件之间是或的关系)
        NativeSearchQuery query = null;
        if(keyWord.getKeyWord()==null || keyWord.getKeyWord().equals("")) {
            query = builder.withPageable(pageable).build();
        }
        else {

            query = builder.withPageable(pageable)
                    .withQuery(QueryBuilders.multiMatchQuery(keyWord.getKeyWord(), "blogTitle", "blogContext"))
                    .withHighlightBuilder(highlightBuilder)
                    .withSort(order)
                    .build();
        }

        // 开始查询
        long count = elasticsearchRestTemplate.count(query, TbBlog.class);
        System.out.println("count="+count);
        SearchHits<TbBlog> searchHits = elasticsearchRestTemplate.search(query, TbBlog.class);

        // 遍历查询结果
        ArrayList<TbBlog> tbBlogs = new ArrayList<>();
        searchHits.getSearchHits().forEach(item -> {
            TbBlog blog = item.getContent();

            List<String> titles = item.getHighlightField("blogTitle");
            if(titles!=null && titles.size()>0) {
                blog.setBlogTitle(titles.get(0));
            }

            tbBlogs.add(blog);
        });

        // 分页计算
        HashMap<String, Object> map = new HashMap<>();
        map.put("records", tbBlogs);
        // 总记录数/当前页号/每页记录数
        map.put("count", count);
        map.put("pageNum", keyWord.getPageNum()+1);
        map.put("pageSize", keyWord.getPageSize());
        // 总页数
        long pageCount = (count%keyWord.getPageSize()>0)?count/keyWord.getPageSize()+1:count/keyWord.getPageSize();
        map.put("pageCount", pageCount);

        return ResultResponse.SUCCESS(map);
    }

    /**
     * 调用 ES 获取 IK 分词后结果
     *
     * @param searchContent
     */
//    private List<String> getIkAnalyzeSearchTerms(String searchContent, String ikAnalyzer) {
//
//        // 调用 IK 分词分词
//        AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(),
//                AnalyzeAction.INSTANCE, "infomations", searchContent);
//
//        ikRequest.setTokenizer(ikAnalyzer);
//        List<AnalyzeResponse.AnalyzeToken> tokenList = ikRequest.execute().actionGet().getTokens();
//
//        // 循环赋值
//        List<String> searchTermList = new ArrayList<>();
//        tokenList.forEach(ikToken -> {
//            searchTermList.add(ikToken.getTerm());
//        });
//        return searchTermList;
//
//    }
}
